/*
 * chat_message.c
 *
 *  Created on: 2012-6-30
 *      Author: rendong
 */
#include "chat_message.h"
#include "../lib/md5.h"

#define INT32VAL(buffer) (*(int *)(buffer))
#define INT16VAL(buffer) (*(short *)(buffer))

#define SET_INT32(buffer, intval) (*(int *)(buffer) = (intval))
#define SET_INT16(buffer, intval) (*(short *)(buffer) = (intval))

static char *read_str(char *buffer, int buffer_len);
static int add_channel(char * name, chat_session_t *session);
static void chat_send_error(chat_session_t * session, int error_type);


static void chat_handle_login(chat_session_t * session, short pack_type, int buffer_len, char *buffer);
static void chat_handle_friendlist(chat_session_t * session, short pack_type, int buffer_len, char *buffer);
static void chat_handle_channel(chat_session_t * session, short pack_type, int buffer_len, char *buffer);
static void chat_handle_channel_out(chat_session_t * session, short pack_type, int buffer_len, char *buffer);
static void chat_handle_chat(chat_session_t * session, short pack_type, int buffer_len, char *buffer);
static void chat_handle_query(chat_session_t * session, short pack_type, int buffer_len, char *buffer);
static void chat_handle_disable(chat_session_t * session, short pack_type, int buffer_len, char *buffer);
static void chat_handle_heart(chat_session_t * session, short pack_type, int buffer_len, char *buffer);
static int check_user_disable(chat_session_t * session);

/**
 * 从buffer中读取字符串
 * buffer 从len位置开始
 * buffer_len 剩下的位置
 */
static char *read_str(char *buffer, int buffer_len)
{
	int str_len;
	char *str=NULL;

	if (buffer_len < INT32_LEN){
		return str;
	}

	str_len = INT32VAL(buffer);
	//chat_log_debug("read_str:buffer_len:%d, str_len:%d\n", buffer_len, str_len);

	if (str_len <= buffer_len - INT32_LEN){
		str = malloc(str_len +1);
		memset(str, 0, str_len+1);
		memcpy(str, buffer+INT32_LEN, str_len);
	}

	return str;
}

/**
 * 发送标准错误
 */
static void chat_send_error(chat_session_t * session, int error_type)
{
	static char *ret_buffers[255] = {NULL};

	if (ret_buffers[error_type] == NULL){// init
		ret_buffers[error_type] = malloc(INT32_LEN + INT16_LEN + INT32_LEN);
		memset(ret_buffers[error_type], 0, INT32_LEN + INT16_LEN + INT32_LEN);

		*(int *)ret_buffers[error_type] = INT16_LEN + INT32_LEN;// pkg_len
		*(int *)(ret_buffers[error_type]+ INT32_LEN) = 5;// pkg_type
		*(int *)(ret_buffers[error_type]+ INT32_LEN+INT16_LEN) = error_type;
	}

	chat_log_debug("error: uid:%s error_type:%d\n", session->uid, error_type);

	chat_send(session, ret_buffers[error_type], INT32_LEN + INT16_LEN + INT32_LEN, 0);
}

/**
 * 加入频道
 * 失败返回1 成功返回0
 */
static int add_channel(char * name, chat_session_t *session)
{
	chat_list_t *channel_list;
	int i;
	char *old_name;

	if (session->channel_name_size >= cfg_maxchannels)
		return 1;

	for(i = 0; i < session->channel_name_size; i++){
		old_name = session->channel_name_list[i];

		if (old_name == NULL)
			continue;

		if (strcmp(old_name, name) == 0)
			return 1;
	}

	session->channel_name_list[session->channel_name_size++] = name;

	channel_list = chat_hash_get(session->config->all_channel, name);

	if (channel_list == NULL){
		chat_log_debug("channel_list is null:%s\n", name);
		channel_list = chat_list_create();
		chat_hash_put(session->config->all_channel, name,channel_list);
	}

	chat_list_push(channel_list, session);

	return 0;
}

/**
 * 处理消息
 */
void chat_handle_message(chat_session_t * session, short pack_type, int buffer_len, char *buffer)
{
	switch(pack_type)	{
		case 1:
			chat_handle_heart(session, pack_type, buffer_len, buffer);
			break;
		case 100:
			chat_handle_login(session, pack_type, buffer_len, buffer);
			break;
		case 103:
			if (session->login_type == LOGIN_TYPE_USER)
				chat_handle_friendlist(session, pack_type, buffer_len, buffer);
			else
				chat_send_error(session, ERROR_TYPE_NOTLOGIN);
			break;
		case 107:
				if (session->login_type == LOGIN_TYPE_USER)
					chat_handle_channel(session, pack_type, buffer_len, buffer);
				else
					chat_send_error(session, ERROR_TYPE_NOTLOGIN);
				break;
		case 110:
		case 111:
				if (session->login_type == LOGIN_TYPE_USER)
					chat_handle_chat(session, pack_type, buffer_len, buffer);
				else
					chat_send_error(session, ERROR_TYPE_NOTLOGIN);
				break;
		case 114:
			if (session->login_type == LOGIN_TYPE_USER)
				chat_handle_query(session, pack_type, buffer_len, buffer);
			else
				chat_send_error(session, ERROR_TYPE_NOTLOGIN);
			break;
		case 116:
			if (session->login_type == LOGIN_TYPE_USER)
				chat_handle_disable(session, pack_type, buffer_len, buffer);
			else
				chat_send_error(session, ERROR_TYPE_NOTLOGIN);
			break;
		case 118:
			if (session->login_type == LOGIN_TYPE_USER)
				chat_handle_channel_out(session, pack_type, buffer_len, buffer);
			else
				chat_send_error(session, ERROR_TYPE_NOTLOGIN);
			break;
		default:
			chat_log_error("<<<handler_message type not found! len=%d type=%d\n", buffer_len, pack_type);
	}
}


/**
 * 心跳接口
 */
static void chat_handle_heart(chat_session_t * session, short pack_type,  int buffer_len, char *buffer)
{
	// update heart time
	session->heart_time = session->config->t_req_time;

	static char ret_buffer[6] = {0};
	*(int*)ret_buffer = 2;// length = 2
	*(short*)(ret_buffer+INT32_LEN) = 2;// type = 2
	
	chat_send(session, ret_buffer, 6, 0);
}


/**
 * 登陆接口
 * len+type+[strlen+str]+[strlen+str]+[strlen+str]
 * 长度+类型+key+用户id+昵称
 */
static void chat_handle_login(chat_session_t * session, short pack_type,  int buffer_len, char *buffer)
{
	size_t key_len, data_size;
	char *key, *uid=NULL, *nick;
	chat_session_t *old_session;
	char * channel_name;
	int time=0;
	int check_type = 0;
	char bufferstr[1024];

	int ret_status = 1;
	static char *ret_buffers[5] = {NULL};// 最多4中状态

	key_len = *(int *)buffer;
	key = buffer + INT32_LEN;

	if (session->login_type != 0)// 已经登录，则忽略
		return;

	data_size = INT32_LEN + key_len;
	uid = read_str(buffer+data_size, buffer_len - data_size);

	if (uid == NULL){
		ret_status = 3;
	}else{
		session->uid = uid;
	}

	data_size += INT32_LEN + *(int *)(buffer+data_size);
	nick = read_str(buffer+data_size, buffer_len - data_size);

	if (nick == NULL){
		ret_status = 4;
	}else{
		session->nickname = nick;
	}
	data_size += strlen(nick)+INT32_LEN;
	if (buffer_len - data_size == 4){
		time = INT32VAL(buffer + data_size);
	}

	// 解析正常
	if (ret_status == 1){
		if (cfg_login_type == 0){
			if (time == 0){
				check_type = 1;
			}else{
				check_type = 2;
			}
		}else{
			check_type = 2;
		}

		// php 还是走老的方式
		if (check_type != 1 && strncmp(session->uid, "php", 3) == 0){
			check_type = 1;
		}
	}

	if (check_type == 1){ // 老的验证方式
		if (key_len != strlen(cfg_key) || memcmp(cfg_key, key, strlen(cfg_key)) != 0){// 密码错误
			ret_status = 2;
		}
	}else if (check_type == 2){// md5(用户id+昵称+time+slot)
		if (abs(time - session->config->t_req_time) > 30){// 30 秒内有效
			ret_status = 2;
		}else{
			snprintf(bufferstr, 1024, "%s%s%d%s", session->uid, session->nickname, time, cfg_login_slot );
			char * md5 = md5_string(bufferstr);
			if (strlen(key) < 32 || memcmp(md5, key, 32) != 0){
				ret_status = 2;
			}
			free(md5);
		}
	}
	printf("ret_status:%d\n", ret_status);
	// 登陆成功
	if (ret_status == 1){
		session->login_type = LOGIN_TYPE_USER;

		// 重复登陆检测
		old_session = chat_hash_get(session->config->uid_sessions, uid);
		if (old_session != NULL){
			chat_send_error(old_session, ERROR_TYPE_DUPLOGIN);
			chat_epoll_close(old_session->config, old_session->sockfd, CLOSE_DUPLOGIN);
		}

		chat_hash_put(session->config->uid_sessions, uid, session);

		// 加入公共频道
		channel_name = strdup(CHANEL_WORLD);
		add_channel(channel_name, session);

		if (strncmp(session->uid, "php", 3) != 0)
		{
			char * buff_log = malloc(SIZE_LOG_BUFFER);//%s [下线] online=%d uid=%s nick=%s fd=%d
			int log_n = snprintf(buff_log, SIZE_LOG_BUFFER, "%s [上线] online=%d uid=%s nick=%s fd=%d\r\n",
					session->config->s_req_time, session->config->cur_clients, session->uid, session->nickname, session->sockfd);
			chat_file_write(session->config->chat_log_fd, buff_log, log_n);
		}

		if (session->config->chat_phplog_fd != -1)
		{
			char * buff_log_php = malloc(SIZE_LOG_BUFFER);//%s [下线] online=%d uid=%s nick=%s fd=%d
			int log_n_php = snprintf(buff_log_php, SIZE_LOG_BUFFER, "%s [上线] online=%d uid=%s nick=%s fd=%d\r\n",
					session->config->s_req_time, session->config->cur_clients, session->uid, session->nickname, session->sockfd);
			chat_file_write(session->config->chat_phplog_fd, buff_log_php, log_n_php);
		}
	}

	if (ret_buffers[ret_status] == NULL){// init
		ret_buffers[ret_status] = malloc(INT32_LEN + INT16_LEN + INT32_LEN);
		memset(ret_buffers[ret_status], 0, INT32_LEN + INT16_LEN + INT32_LEN);
		ret_buffers[ret_status] = ret_buffers[ret_status];

		*(int *)ret_buffers[ret_status] = INT16_LEN + INT32_LEN;// pkg_len
		*(short *)(ret_buffers[ret_status]+ INT32_LEN) = 101;// pkg_type
		*(int *)(ret_buffers[ret_status]+ INT32_LEN+INT16_LEN) = ret_status;
	}

	chat_send(session, ret_buffers[ret_status], INT32_LEN + INT16_LEN + INT32_LEN, 0);
}

/**
 * 好友列表
 */
static void chat_handle_friendlist(chat_session_t * session, short pack_type, int buffer_len, char *buffer)
{
	int friend_len, i, str_len, data_size, ret_buffer_size,ret_online_num;
	char * fuid;
	char *ret_buffer=NULL;
	chat_session_t *fsession;

	char *fret_buffer;
	int fret_len;

	if (buffer_len < INT32_LEN)
		return;

	friend_len = *(int *)buffer;
	data_size = INT32_LEN;

	ret_online_num = 0;
	if (ret_buffer == NULL){// 直接按照最大长度申请
		ret_buffer = malloc(buffer_len + INT32_LEN + INT16_LEN);
		*(short *)(ret_buffer+INT32_LEN) = 104;
	}

	ret_buffer_size = INT32_LEN + INT16_LEN + INT32_LEN;

	// 重复发送该数据包，则free之前的
	if (session->friend_list != NULL){
		for(i=0; i < session->friend_len; i++){
			fuid = session->friend_list[i];
			if (fuid != NULL)
				free(fuid);
		}

		free(session->friend_list);
	}

	session->friend_len = friend_len;
	session->friend_list = malloc(sizeof(char *) * friend_len);
	memset(session->friend_list, 0, sizeof(char *) * friend_len);

	for(i = 0; i<friend_len; i++){
		fuid = read_str(buffer+data_size, buffer_len - data_size);

		if (fuid == NULL){
			chat_log_debug("fuid is NULL");
			break;
		}

		session->friend_list[i] = fuid;

		str_len = *(int *)(buffer+data_size);
		data_size += str_len + INT32_LEN;

		// 查询是否在线
		fsession = chat_hash_get(session->config->uid_sessions, fuid);

		if (fsession != NULL && strcmp(fuid, session->uid) != 0){
			ret_online_num++;

			*(int *)(ret_buffer + ret_buffer_size) = str_len;
			memcpy(ret_buffer + ret_buffer_size + INT32_LEN, fuid, str_len);
			ret_buffer_size += INT32_LEN + str_len;

			// 给fsession 发送session 上线提醒 len+type+friendid
			str_len = strlen(session->uid);
			fret_len = INT32_LEN + INT16_LEN + INT32_LEN + str_len;
			fret_buffer = malloc(fret_len);

			*(int *)fret_buffer = INT16_LEN + INT32_LEN + str_len;
			*(short *)(fret_buffer+INT32_LEN) = 105;
			*(int *)(fret_buffer+INT32_LEN+INT16_LEN) = str_len;
			memcpy(fret_buffer + INT32_LEN+INT16_LEN+INT32_LEN, session->uid, str_len);

			chat_send(fsession, fret_buffer, fret_len, 1);
		}
	}

	*(int *)ret_buffer = ret_buffer_size - INT32_LEN;// pkg_len
	*(int *)(ret_buffer + INT32_LEN + INT16_LEN) = ret_online_num;

	chat_send(session, ret_buffer, ret_buffer_size, 1);
}

/**
 * 加入频道
 */
static void chat_handle_channel(chat_session_t * session, short pack_type, int buffer_len, char *buffer)
{
	char *channel_name;
	int ret, type, ret_len;
	char *ret_buffer;

	channel_name = read_str(buffer, buffer_len);

	ret = add_channel(channel_name, session);
	type = ret == 0? 108 : 109;

	ret_len =INT32_LEN + INT16_LEN + INT32_LEN + strlen(channel_name);
	ret_buffer = malloc(ret_len);
	*(int *)ret_buffer = ret_len - INT32_LEN;
	*(short *)(ret_buffer+INT32_LEN) = type;
	*(int *)(ret_buffer+ INT32_LEN + INT16_LEN) = strlen(channel_name);
	memcpy(ret_buffer+ INT32_LEN + INT16_LEN + INT32_LEN, channel_name, strlen(channel_name));

	if (ret == 1){
		free(channel_name);
	}

	chat_send(session, ret_buffer, ret_len, 1);
}


/**
 * 退出频道
 */
static void chat_handle_channel_out(chat_session_t * session, short pack_type, int buffer_len, char *buffer)
{
	char *channel_name,*channel_out_name;
	int type, ret_len,i;
	chat_list_t *list;
	char *ret_buffer;
	int flag_out=0;

	channel_out_name = read_str(buffer, buffer_len);

	// 删除加入的频道
	if (session->channel_name_size > 0){
		for(i=0; i<session->channel_name_size;i++){
			channel_name = session->channel_name_list[i];

			if (channel_name == NULL)continue;

			if (strcmp(channel_name, channel_out_name) == 0){
				list = chat_hash_get(session->config->all_channel, channel_name);
				chat_list_del(list, session);
				free(channel_name);

				session->channel_name_list[i] = NULL;
				flag_out = 1;
			}
		}
	}

	type = flag_out == 0? 120 : 119;

	ret_len =INT32_LEN + INT16_LEN + INT32_LEN + strlen(channel_out_name);
	ret_buffer = malloc(ret_len);
	*(int *)ret_buffer = ret_len - INT32_LEN;
	*(short *)(ret_buffer+INT32_LEN) = type;
	*(int *)(ret_buffer+ INT32_LEN + INT16_LEN) = strlen(channel_out_name);
	memcpy(ret_buffer+ INT32_LEN + INT16_LEN + INT32_LEN, channel_out_name, strlen(channel_out_name));

	free(channel_out_name);

	chat_send(session, ret_buffer, ret_len, 1);
}


/**
 * 聊天
 * len+type+message_type+dst_name+message
 */
static void chat_handle_chat(chat_session_t * session, short pack_type, int buffer_len, char *buffer)
{
	int message_type,dst_name_len, message_len, buf_pos;
	char *str_dst_name, *str_message;

	int ret_len;
	char *ret_buffer;
	char *ret_buffer_tmp;

	chat_session_t *d_session;

	buf_pos = 0;

	// 如果被禁止发言，则返回
	if (check_user_disable(session)){
		return;
	}

	message_type = INT32VAL(buffer);
	buf_pos += INT32_LEN;

	dst_name_len = INT32VAL(buffer+buf_pos);
	str_dst_name = read_str(buffer+buf_pos, buffer_len - buf_pos);

	buf_pos += INT32_LEN;
	buf_pos += dst_name_len;

	if (str_dst_name == NULL){
		chat_log_error("chat_handle_chat dst_name is null\n");
		return;
	}

	message_len = INT32VAL(buffer+buf_pos);
	str_message = read_str(buffer+buf_pos, buffer_len -buf_pos);

	if (str_message == NULL){
		free(str_dst_name);
		chat_log_error("chat_handle_chat message is null\n");
		return;
	}


	// 处理消息
	if (pack_type == 110){// 频道信息
		ret_len = INT32_LEN + INT16_LEN + INT32_LEN
				+ INT32_LEN+strlen(session->uid)
				+ INT32_LEN+strlen(session->nickname)
				+ INT32_LEN + dst_name_len
				+ INT32_LEN + message_len;

		ret_buffer = malloc(ret_len);

		SET_INT32(ret_buffer, ret_len - INT32_LEN);
		buf_pos = INT32_LEN;

		SET_INT16(ret_buffer+buf_pos, 112);
		buf_pos += INT16_LEN;

		SET_INT32(ret_buffer+buf_pos, message_type);
		buf_pos += INT32_LEN;

		SET_INT32(ret_buffer+buf_pos, strlen(session->uid));
		buf_pos += INT32_LEN;
		memcpy(ret_buffer+buf_pos, session->uid, strlen(session->uid));
		buf_pos += strlen(session->uid);

		SET_INT32(ret_buffer+buf_pos, strlen(session->nickname));
		buf_pos += INT32_LEN;
		memcpy(ret_buffer+buf_pos, session->nickname, strlen(session->nickname));
		buf_pos += strlen(session->nickname);

		SET_INT32(ret_buffer+buf_pos, dst_name_len);
		buf_pos += INT32_LEN;
		memcpy(ret_buffer+buf_pos, str_dst_name, dst_name_len);
		buf_pos += dst_name_len;

		SET_INT32(ret_buffer+buf_pos, message_len);
		buf_pos += INT32_LEN;
		memcpy(ret_buffer+buf_pos, str_message, message_len);

		chat_log_debug("uid:%s, nick:%s dst_name:%s, messag:%s\n", session->uid, session->nickname,str_dst_name, str_message);

		if (strncmp(session->uid, "php", 3) != 0){
			char * buff_log = malloc(SIZE_LOG_BUFFER);
			int log_n = snprintf(buff_log, SIZE_LOG_BUFFER, "%s [频道] %s uid=%s nick=%s msg=%s\r\n",
					session->config->s_req_time, str_dst_name, session->uid, session->nickname,str_message);

			chat_file_write(session->config->chat_log_fd, buff_log, log_n);
		}
		if (session->config->chat_phplog_fd != -1){
			char * buff_log = malloc(SIZE_LOG_BUFFER);
			int log_n = snprintf(buff_log, SIZE_LOG_BUFFER, "%s [频道] %s uid=%s nick=%s msg=%s\r\n",
					session->config->s_req_time, str_dst_name, session->uid, session->nickname,str_message);

			chat_file_write(session->config->chat_phplog_fd, buff_log, log_n);
		}

		chat_list_t *list = chat_hash_get(session->config->all_channel, str_dst_name);
		if (list != NULL){
			chat_list_item_t *head;
			head = list->head;
			while(head != NULL){
				ret_buffer_tmp = malloc(ret_len);
				memcpy(ret_buffer_tmp, ret_buffer, ret_len);

				chat_send((chat_session_t *)(head->elts), ret_buffer_tmp, ret_len, 1);
				if (session->config->chat_phplog_fd != -1){
					char * buff_log_list = malloc(SIZE_LOG_BUFFER);
					int log_n = snprintf(buff_log_list, SIZE_LOG_BUFFER, "to => %s [频道] %s uid=%s nick=%s msg=%s\r\n",
					session->config->s_req_time, str_dst_name, session->uid, session->nickname,str_message);

					chat_file_write(session->config->chat_phplog_fd, buff_log_list, log_n);
				}
				chat_log_debug("send to uid:%s\n", ((chat_session_t *)(head->elts))->uid);

				head = head->next;
			}
		}else{
			chat_log_error("chat_handle_chat channel not found %s\n", str_dst_name);
		}


		free(ret_buffer);
	}else if (pack_type == 111){// 私聊 发送私聊信息 type=111 dst_name=接受方用户编号
		d_session = chat_hash_get(session->config->uid_sessions, str_dst_name);
		if (d_session == NULL){
			chat_send_error(session, 3);
		}else{
			/**
			 * len+type+message_type+src_id+src_name+dst_name+message
长度+类型+消息类型+发送用户编号+发送用户名+名称+接收消息内容
频道信息 type=112	dst_name=接收频道名称
私聊信息 type=113	dst_name=接收方用户编号
			 */
			ret_len = INT32_LEN + INT16_LEN + INT32_LEN
					+ INT32_LEN+strlen(session->uid)
					+ INT32_LEN+strlen(session->nickname)
					+ INT32_LEN + strlen(d_session->uid)
					+ INT32_LEN + message_len;

			ret_buffer = malloc(ret_len);

			SET_INT32(ret_buffer, ret_len - INT32_LEN);
			buf_pos = INT32_LEN;

			SET_INT16(ret_buffer+buf_pos, 113);
			buf_pos += INT16_LEN;

			SET_INT32(ret_buffer+buf_pos, message_type);
			buf_pos += INT32_LEN;

			SET_INT32(ret_buffer+buf_pos, strlen(session->uid));
			buf_pos += INT32_LEN;
			memcpy(ret_buffer+buf_pos, session->uid, strlen(session->uid));
			buf_pos += strlen(session->uid);

			SET_INT32(ret_buffer+buf_pos, strlen(session->nickname));
			buf_pos += INT32_LEN;
			memcpy(ret_buffer+buf_pos, session->nickname, strlen(session->nickname));
			buf_pos += strlen(session->nickname);

			SET_INT32(ret_buffer+buf_pos, strlen(d_session->uid));
			buf_pos += INT32_LEN;
			memcpy(ret_buffer+buf_pos, d_session->uid, strlen(d_session->uid));
			buf_pos += strlen(d_session->uid);

			SET_INT32(ret_buffer+buf_pos, message_len);
			buf_pos += INT32_LEN;
			memcpy(ret_buffer+buf_pos, str_message, message_len);

			ret_buffer_tmp = malloc(ret_len);
			memcpy(ret_buffer_tmp, ret_buffer, ret_len);

			if (strncmp(session->uid, "php", 3) != 0)
			{
				char * buff_log = malloc(SIZE_LOG_BUFFER);
				int log_n = snprintf(buff_log, SIZE_LOG_BUFFER,
						"%s [私聊] suid=%s snick=%s touid=%s tonick=%s msg=%s\r\n",
						session->config->s_req_time, session->uid, session->nickname,
						d_session->uid, d_session->nickname,str_message);
				chat_file_write(session->config->chat_log_fd, buff_log, log_n);
			}
			if (session->config->chat_phplog_fd != -1){
				char * buff_log = malloc(SIZE_LOG_BUFFER);
				int log_n = snprintf(buff_log, SIZE_LOG_BUFFER,
				"%s [私聊] suid=%s snick=%s touid=%s tonick=%s msg=%s\r\n",
				session->config->s_req_time, session->uid, session->nickname,
				d_session->uid, d_session->nickname,str_message);
				chat_file_write(session->config->chat_phplog_fd, buff_log, log_n);
			}

			chat_send(d_session, ret_buffer, ret_len, 1);
			if (session != NULL)
				chat_send(session, ret_buffer_tmp, ret_len, 1);
		}
	}

	free(str_dst_name);
	free(str_message);
}

/**
 * 禁言接口
 */
static void chat_handle_disable(chat_session_t * session, short pack_type, int buffer_len, char *buffer)
{
	char *uid;
	int time_sec, buffer_pos=0;

	uid = read_str(buffer, buffer_len);
	buffer_pos += 4 + strlen(uid);

	time_sec = INT32VAL(buffer+buffer_pos);

	chat_disable_user_t * dis = NULL;

	dis = chat_hash_get(session->config->uid_disable, uid);

	if (dis == NULL)
	{
		dis = malloc(sizeof(chat_disable_user_t));
		memset(dis, 0, sizeof(chat_disable_user_t));
		chat_hash_put(session->config->uid_disable, uid, dis);
	}

	dis->time = time_sec;
	time(&dis->now);

	// 删除
	if (time_sec <= 0){
		free(dis);
		chat_hash_del(session->config->uid_disable, uid);
	}

	free(uid);
	chat_log_debug("uid:%s time:%d\n", uid, time_sec);
}

/**
 * 检测用户是否被禁言
 * 返回 1，则被禁言
 */
static int check_user_disable(chat_session_t * session)
{
	chat_disable_user_t * dis = NULL;
	time_t now;

	struct tm *expire_time;
	char tmpbuf[128] = {0};

	char * ret_buffer;
	int ret_pos, ret_len;

	dis = chat_hash_get(session->config->uid_disable, session->uid);

	if (dis == NULL)
		return 0;

	time(&now);

	if (now < (dis->now + dis->time)){
		now = dis->now + dis->time;
		expire_time=localtime(&now);

		strftime( tmpbuf, 128, "%Y-%m-%d %H:%M:%S", expire_time);

		ret_len = INT32_LEN + INT16_LEN + INT32_LEN + strlen(tmpbuf);
		ret_buffer = malloc(ret_len);


		SET_INT32(ret_buffer, ret_len-INT32_LEN);
		ret_pos = INT32_LEN;

		SET_INT16(ret_buffer+ret_pos, 117);
		ret_pos += INT16_LEN;


		SET_INT32(ret_buffer+ret_pos, strlen(tmpbuf));
		ret_pos += INT32_LEN;

		memcpy(ret_buffer + ret_pos, tmpbuf, strlen(tmpbuf));

		chat_send(session, ret_buffer, ret_len, 1);
		return 1;
	}else{// 禁言时间已过，则删除
		free(dis);
		chat_hash_del(session->config->uid_disable, session->uid);
	}

	return 0;
}

/**
 * 查询接口
 */
static void chat_handle_query(chat_session_t * session, short pack_type, int buffer_len, char *buffer)
{
	int sub_type, ret_len, ret_pos;

	char *ret_buffer;
	char *str;

	sub_type = INT32VAL(buffer);

	int len,i;

	len = 0;
	for(i=0; i< session->config->cfg_max_clients; i++){
		if (session->config->fd_sessions[i] != NULL)
			len++;
	}


	if (sub_type == 1){
		str = malloc(1024);
		memset(str, 0, 1024);
		sprintf(str, "currclients:%d maxclients:%d sessionNum:%d maxfd:%d lastfd:%d",
				session->config->cur_clients,
				session->config->stat_max_clients,
				len,
				session->config->stat_max_fd,
				session->config->stat_last_fd
		);

		ret_len = INT32_LEN + INT16_LEN + INT32_LEN+ INT32_LEN + strlen(str);
		ret_buffer = malloc(ret_len);
		ret_pos = 0;

		SET_INT32(ret_buffer, ret_len - INT32_LEN);
		ret_pos += INT32_LEN;

		SET_INT16(ret_buffer+ret_pos, 115);
		ret_pos += INT16_LEN;

		SET_INT32(ret_buffer+ret_pos, sub_type);
		ret_pos += INT32_LEN;

		SET_INT32(ret_buffer + ret_pos, strlen(str));
		ret_pos += INT32_LEN;

		memcpy(ret_buffer+ret_pos, str, strlen(str));

		chat_send(session, ret_buffer, ret_len, 1);
		free(str);
	}else if (sub_type == 2){// 返回session列表
		len = session->config->cur_clients * 300; // 每个人200个字节
		str = malloc(len);
		memset(str, 0, len);

		chat_session_t * csession;
		int str_pos = 0;
		char buff[300];
		char stime[256];
		struct tm *now_time;

		for(i=0; i< session->config->cfg_max_clients; i++){
			if (session->config->fd_sessions[i] != NULL){
				csession = session->config->fd_sessions[i];
				
				now_time = localtime(&csession->login_time);
				strftime( stime, 256, "%Y-%m-%d %H:%M:%S", now_time);

				sprintf(buff, "fd=%d uid=%s nick=%s ltime=%s\n",
						csession->sockfd,
						csession->uid,
						csession->nickname,
						stime
						);

				strcpy(str+str_pos, buff);
				str_pos += strlen(buff);

				if (str_pos > len- 300)break;
			}
		}

		ret_len = INT32_LEN + INT16_LEN + INT32_LEN+ INT32_LEN + strlen(str);
		ret_buffer = malloc(ret_len);
		ret_pos = 0;

		SET_INT32(ret_buffer, ret_len - INT32_LEN);
		ret_pos += INT32_LEN;

		SET_INT16(ret_buffer+ret_pos, 115);
		ret_pos += INT16_LEN;

		SET_INT32(ret_buffer+ret_pos, sub_type);
		ret_pos += INT32_LEN;

		SET_INT32(ret_buffer + ret_pos, strlen(str));
		ret_pos += INT32_LEN;

		memcpy(ret_buffer+ret_pos, str, strlen(str));

		chat_send(session, ret_buffer, ret_len, 1);
		free(str);
	}
}
